~ chicken-core (chicken-5) /manual/Module (chicken syntax)
Trap1[[tags: manual]]
2[[toc:]]
3
4== Module (chicken syntax)
5
6This module has support for syntax- and module handling. This module
7is used by default, unless a program is compiled with the
8{{-explicit-use}} option.
9
10=== Macro transformers
11
12Macro transformers are procedures you can use in a {{define-syntax}}
13context to register a procedure that can transform s-expressions into
14other s-expressions. Only use these when you need to break hygiene in
15a controlled way; for many use cases {{syntax-rules}} is more
16appropriate, as it offers stronger guarantees of hygiene, is more
17high-level and is standard R5RS Scheme.
18
19For those situations where you need more control, however, CHICKEN
20supports two kinds of low-level macros: so-called explicit renaming
21and implicit renaming macros.
22
23==== Explicit renaming macros
24
25The low-level macro facility that CHICKEN provides is called "explicit
26renaming" and allows writing hygienic or non-hygienic macros
27procedurally. When given the return value of one of the
28procedures {{er-macro-transformer}} or {{ir-macro-transformer}}
29instead of a {{syntax-rules}} form, {{define-syntax}} evaluates the
30procedure in a distinct expansion environment (initially having access
31to the exported identifiers of the {{scheme}} module). The procedure
32takes an expression and two other arguments and returns a transformed
33expression.
34
35For example, the transformation procedure for a {{call}} macro such
36that {{(call proc arg ...)}} expands into {{(proc arg ...)}} can be
37written as
38
39 (er-macro-transformer
40 (lambda (exp rename compare)
41 (cdr exp)))
42
43Expressions are represented as lists in the traditional manner,
44except that identifiers are represented as special uninterned symbols.
45
46The second argument to a transformation procedure is a renaming procedure that
47takes the representation of an identifier as its argument and returns the
48representation of a fresh identifier that occurs nowhere else in the
49program. For example, the transformation procedure for a simplified
50version of the {{let}} macro might be written as
51
52 (er-macro-transformer
53 (lambda (exp rename compare)
54 (let ((vars (map car (cadr exp)))
55 (inits (map cadr (cadr exp)))
56 (body (cddr exp)))
57 `((lambda ,vars ,@body)
58 ,@inits))))
59
60This would not be hygienic, however. A hygienic {{let}} macro must
61rename the identifier {{lambda}} to protect it from being captured by
62a local binding. The renaming effectively creates a fresh alias for
63{{lambda}}, one that cannot be captured by any subsequent binding:
64
65 (er-macro-transformer
66 (lambda (exp rename compare)
67 (let ((vars (map car (cadr exp)))
68 (inits (map cadr (cadr exp)))
69 (body (cddr exp)))
70 `((,(rename 'lambda) ,vars ,@body)
71 ,@inits))))
72
73The expression returned by the transformation procedure will be
74expanded in the syntactic environment obtained from the syntactic
75environment of the macro application by binding any fresh identifiers
76generated by the renaming procedure to the denotations of the original
77identifiers in the syntactic environment in which the macro was
78defined. This means that a renamed identifier will denote the same
79thing as the original identifier unless the transformation procedure
80that renamed the identifier placed an occurrence of it in a binding
81position.
82
83Identifiers obtained from any two calls to the renaming procedure with
84the same argument will necessarily be the same, but will denote the
85same syntactical binding. It is an error if the renaming procedure is
86called after the transformation procedure has returned.
87
88The third argument to a transformation procedure is a comparison
89predicate that takes the representations of two identifiers as its
90arguments and returns true if and only if they denote the same thing
91in the syntactic environment that will be used to expand the
92transformed macro application. For example, the transformation
93procedure for a simplified version of the {{cond}} macro can be written
94as
95
96 (er-macro-transformer
97 (lambda (exp rename compare)
98 (let ((clauses (cdr exp)))
99 (if (null? clauses)
100 `(,(rename 'quote) unspecified)
101 (let* ((first (car clauses))
102 (rest (cdr clauses))
103 (test (car first)))
104 (cond ((and (symbol? test)
105 (compare test (rename 'else)))
106 `(,(rename 'begin) ,@(cdr first)))
107 (else `(,(rename 'if)
108 ,test
109 (,(rename 'begin) ,@(cdr first))
110 (,(rename 'cond) ,@rest)))))))))
111
112In this example the identifier {{else}} is renamed before being passed
113to the comparison predicate, so the comparison will be true if and
114only if the test expression is an identifier that denotes the same
115thing in the syntactic environment of the expression being transformed
116as {{else}} denotes in the syntactic environment in which the {{cond}}
117macro was defined. If {{else}} were not renamed before being passed to
118the comparison predicate, then it would match a local variable that
119happened to be named {{else}}, and the macro would not be hygienic.
120The final recursive call to {{cond}} also needs to be renamed because
121someone might create an alias for this macro and use it in a {{let}}
122where {{cond}} is an ordinary variable.
123
124Some macros are non-hygienic by design. For example, the
125following defines a {{loop}} macro that implicitly binds {{exit}} to an
126escape procedure. The binding of {{exit}} is intended to capture free
127references to {{exit}} in the body of the loop, so {{exit}} is not
128renamed.
129
130 (define-syntax loop
131 (er-macro-transformer
132 (lambda (x r c)
133 (let ((body (cdr x)))
134 `(,(r 'call-with-current-continuation)
135 (,(r 'lambda) (exit)
136 (,(r 'let) ,(r 'f) () ,@body (,(r 'f)))))))))
137
138Suppose a {{while}} macro is implemented using {{loop}}, with the intent
139that {{exit}} may be used to escape from the {{while}} loop. The {{while}}
140macro cannot be written as
141
142 (define-syntax while
143 (syntax-rules ()
144 ((while test body ...)
145 (loop (if (not test) (exit #f))
146 body ...))))
147
148because the reference to {{exit}} that is inserted by the {{while}} macro
149is intended to be captured by the binding of {{exit}} that will be
150inserted by the {{loop}} macro. In other words, this {{while}} macro is
151not hygienic. Like {{loop}}, it must be written using procedurally:
152
153 (define-syntax while
154 (er-macro-transformer
155 (lambda (x r c)
156 (let ((test (cadr x))
157 (body (cddr x)))
158 `(,(r 'loop)
159 (,(r 'if) (,(r 'not) ,test) (exit #f))
160 ,@body)))))
161
162Think about it: If we ''did'' rename {{exit}}, it would refer to an
163{{exit}} procedure existing in the context of the macro's definition.
164That one [[Unit library#exit|actually exists]]; it is the procedure
165that exits the Scheme interpreter. Definitely ''not'' the one we want :)
166So now we make it refer to an {{exit}} that's locally bound in the
167environment where the macro is expanded.
168
169Note: this implementation of explicit-renaming macros allows passing
170arbitrary expressions to the renaming and comparison procedures. When
171being renamed, a fresh copy of the expression will be produced, with all
172identifiers renamed appropriately. Comparison also supports arbitrary
173expressions as arguments.
174
175
176===== er-macro-transformer
177
178<procedure>(er-macro-transformer TRANSFORMER)</procedure>
179
180Returns an explicit-renaming macro transformer procedure created from
181the procedural macro body {{TRANSFORMER}}, which is a procedure of
182three arguments.
183
184This procedure will be called on expansion with the complete
185s-expression of the macro invocation, a rename procedure that
186hygienically renames identifiers and a comparison procedure that
187compares (possibly renamed) identifiers (see the section "Explicit
188renaming macros" below for a detailed explanation on non-R5RS macros).
189
190Implementation note: this procedure currently just returns its
191argument unchanged and is available for writing low-level macros in a
192more portable fashion, without hard-coding the signature of a
193transformer procedure.
194
195=== Implicit renaming macros
196
197Explicit renaming macros generally require the user to perform quite a
198few renames, because most identifiers that aren't taken from the input
199expression should generally be inserted hygienically. It would make
200more sense to give the output expression as-is, and only explicitly
201convert those identifiers that you want to treat as ''unhygienic''.
202
203This can be done with implicit renaming macros. They just swap the
204default insertion "mode" from unhygienic to hygienic, so to speak.
205Here's the {{cond}} example from the previous section as an ir-macro:
206
207
208 (ir-macro-transformer
209 (lambda (exp inject compare)
210 (let ((clauses (cdr exp)))
211 (if (null? clauses)
212 `(quote unspecified)
213 (let* ((first (car clauses))
214 (rest (cdr clauses))
215 (test (car first)))
216 (cond ((and (symbol? test)
217 (compare test 'else))
218 `(begin ,@(cdr first)))
219 (else `(if ,test
220 (begin ,@(cdr first))
221 (cond ,@rest)))))))))
222
223In this example the identifier {{else}} does ''not'' need to be renamed
224before being passed to the comparison predicate because it is already
225''implicitly'' renamed. This comparison will also be true if and
226only if the test expression is an identifier that denotes the same
227thing in the syntactic environment of the expression being transformed
228as {{else}} denotes in the syntactic environment in which the {{cond}}
229macro was defined. If {{else}} were not renamed before being passed to
230the comparison predicate, then it would match a local variable that
231happened to be named {{else}}, and the macro would not be hygienic.
232
233As you can see, the code is a lot clearer because it isn't obscured
234by excessive renaming.
235
236Here's the {{loop}} macro so you can see how hygiene can be broken
237with implicit renaming macros:
238
239 (define-syntax loop
240 (ir-macro-transformer
241 (lambda (expr inject compare)
242 (let ((body (cdr expr)))
243 `(call-with-current-continuation
244 (lambda (,(inject 'exit))
245 (let f () ,@body (f))))))))
246
247The {{while}} macro is a little trickier: do we inject the call to
248{{exit}} or not? Just like the explicit renaming macro version
249did ''not'' rename it, we must inject it to allow it to be captured
250by the {{loop}} macro:
251
252 (define-syntax while
253 (ir-macro-transformer
254 (lambda (expr inject compare)
255 (let ((test (cadr expr))
256 (body (cddr expr)))
257 `(loop
258 (if (not ,test) (,(inject 'exit) #f))
259 ,@body)))))
260
261Note: Just like explicit renaming macros, this implementation of
262implicit renaming macros allow passing arbitrary expressions to
263the injection and comparison procedures. The injection procedure
264also return fresh copies of its input.
265
266
267===== ir-macro-transformer
268
269<procedure>(ir-macro-transformer TRANSFORMER)</procedure>
270
271This procedure accepts a ''reverse'' syntax transformer, also known as
272an ''implicit renaming macro transformer''. This is a transformer which
273works almost like er-macro-transformer, except the rename and compare
274procedures it receives work a little differently.
275
276The rename procedure is now called {{inject}} and instead of renaming
277the identifier to be resolved in the macro's definition environment,
278it will explicitly ''inject'' the identifier to be resolved in the
279expansion environment. Any non-injected identifiers in the output
280expression produced by the transformer will be implicitly renamed to
281refer to the macro's environment instead. All identifiers in the
282input expression are of course implicitly injected just like with
283explicit renaming macros. See the section above for a more complete
284explanation.
285
286To compare an input identifier you can generally compare to the bare
287symbol and only free identifiers will match. In practice, this means
288that when you would call e.g. {{(compare (cadr expression) (rename
289'x))}} in an ER macro, you simply call {{(compare (cadr expression)
290'x)}} in the IR macro. Likewise, an ''unhygienic'' ER macro's
291comparison {{(compare sym 'abc)}} should be written as {{(compare sym
292(inject 'abc))}} in an IR macro.
293
294
295=== Expanding macros
296
297==== expand
298
299<procedure>(expand X)</procedure>
300
301If {{X}} is a macro-form, expand the macro (and repeat expansion
302until expression is a non-macro form). Returns the resulting expression.
303
304=== Macro helper procedures
305
306==== begin-for-syntax
307
308<macro>(begin-for-syntax EXP ...)</macro>
309
310Equivalent to {{(begin EXP ...)}}, but performs the evaluation of the
311expression during macro-expansion time, using the macro environment
312rather than the interaction environment.
313
314You can use this to define your own helper procedures that you can
315call from a syntax transformer.
316
317==== define-for-syntax
318
319<macro>(define-for-syntax (NAME VAR ...) EXP1 ...)</macro><br>
320<macro>(define-for-syntax (NAME VAR1 ... VARn . VARn+1) EXP1 ...)</macro><br>
321<macro>(define-for-syntax NAME [VALUE])</macro>
322
323Defines the toplevel variable {{NAME}} at macro-expansion time. This
324can be helpful when you want to define support procedures for use in
325macro-transformers, for example.
326
327Essentially, this is a shorthand for
328{{(begin-for-syntax (define ...))}}.
329
330Note that {{define-for-syntax}} definitions within a module are
331implicitly added to that module's import library. Refer to the
332documentation on [[Modules#import-libraries|import libraries]]
333for more information.
334
335
336==== syntax
337
338<procedure>(syntax EXPRESSION)</procedure>
339
340This will quote the {{EXPRESSION}} for use in a syntax expansion. Any
341syntactic information will be stripped from the {{EXPRESSION}}.
342
343
344==== strip-syntax
345
346<procedure>(strip-syntax EXPRESSION)</procedure>
347
348Strips all syntactical information from {{EXPRESSION}}, returning a
349new expression where symbols have all context-information removed.
350
351You should use this procedure whenever you want to manually construct
352new identifiers, which an unhygienic macro can insert. In some cases
353it does not ''appear'' to be necessary to strip context information
354when you use the macro, but you still should do it. Sometimes
355identifiers will not have been renamed (most often at toplevel), but
356there may be other contexts in which identifiers ''will'' have been
357renamed.
358
359==== read-with-source-info
360
361<procedure>(read-with-source-info [port])</procedure>
362
363Exactly like {{{read}}} from the {{{scheme}}} module, except it
364registers the expression it read into the line number database, so
365that if {{{(read-with-source-info)}}} returns {{{OBJ}}},
366{{{(get-line-number OBJ)}}} will return the line number in {{{port}}}.
367
368The port argument may be omitted, in which case it defaults to the
369value returned by {{current-input-port}}. It is an error to read from
370a closed port.
371
372==== get-line-number
373
374<procedure>(get-line-number EXPR)</procedure>
375
376If {{EXPR}} is a pair with the car being a symbol, and line-number
377information is available for this expression, then this procedure
378returns the associated source file and line number as a string. If
379line-number information is not available, then {{#f}} is returned.
380
381==== syntax-error
382
383<procedure>(syntax-error [LOCATION] MESSAGE ARGUMENT ...)</procedure>
384
385Signals an exception of the kind {{(exn syntax)}}. Otherwise identical
386to {{error}}.
387
388
389=== Compiler macros
390
391==== define-compiler-syntax
392
393<macro>(define-compiler-syntax NAME)</macro><br>
394<macro>(define-compiler-syntax NAME TRANSFORMER)</macro><br>
395
396Defines what is usually called a ''compiler macro'' in Lisp: {{NAME}}
397should be the name of a globally or locally bound procedure. Any
398direct call to this procedure will be transformed before compilation,
399which allows arbitrary rewritings of function calls.
400
401{{TRANSFORMER}} can be a {{syntax-rules}} expression or a transformer
402procedure (as returned by {{er-macro-transformer}} or
403{{ir-macro-transformer}}). Returning the original form in an
404explicit/implicit-renaming macro or simply "falling trough" all
405patterns in a {{syntax-rules}} form will keep the original expression
406and compile it normally.
407
408In the interpreter this form does nothing and returns an unspecified
409value.
410
411Compiler-syntax is always local to the current compilation unit and
412can not be exported. Compiler-syntax defined inside a module is not
413visible outside of that module.
414
415{{define-compiler-syntax}} should only be used at top-level. Local
416compiler-syntax can be defined with {{let-compiler-syntax}}.
417
418<enscript highlight=scheme>
419(define-compiler-syntax +
420 (syntax-rules ()
421 ((_) 1)
422 ((_ x 0) x) ) )
423</enscript>
424
425If no transformer is given, then {{(define-compiler-syntax NAME)}}
426removes any compiler-syntax definitions for {{NAME}}.
427
428
429==== let-compiler-syntax
430
431<macro>(let-compiler-syntax ((NAME [TRANSFORMER]) ...) BODY ...)</macro>
432
433Allows definition local compiler macros, which are only applicable
434inside {{BODY ...}}. By not providing a {{TRANSFORMER}} expression,
435compiler-syntax for specific identifiers can be temporarily disabled.
436
437---
438Previous: [[Module (chicken string)]]
439
440Next: [[Module (chicken tcp)]]